# -*- coding: utf-8 -*-
# @Organization  : asiainfo
# @Author        : 周伟东
# @Time          : 2021/1/7 16:39
# @Function      : job 数据库操作类
import logging
from datetime import datetime
from operator import and_

from app.constants import JOB_STATUS_FAILED, JOB_STATUS_START, JOB_STATUS_END, JOB_STATUS_PAUSE, \
    ASSET_JOB_COMPLETE_WRITE_JOB_TO_TABLE_WEIGHT
from app.dao import Session
from app.dao.base_dao import BaseDao
from app.models import CyberspaceJob, CyberspaceAssetResult, CyberspaceHistoryResult


class JobDao(BaseDao):
    def find_job(self, job_id):
        """
        desc：查找Job
        param: job_id
        return: job
        """
        session = Session()
        try:
            job = session.query(CyberspaceJob).filter(CyberspaceJob.job_id == job_id).one()
            return job
        except Exception as e:
            logging.error("查找任务失败", e)
        finally:
            session.close()

    def update_job_status(self, job):
        """
        desc: 更新任务状态
        param: job 任务
        return: True or False
       """
        session = Session()
        try:
            data = {}
            if job.job_start_time:
                data["job_start_time"] = job.job_start_time
            if job.job_end_time:
                data["job_end_time"] = job.job_end_time
                data["job_consume_time"] = job.job_consume_time
            if job.job_result:
                data["job_result"] = job.job_result
            data["job_status"] = job.job_status
            session.query(CyberspaceJob).filter(CyberspaceJob.job_id == job.job_id).update(data)
            session.commit()
            return True
        except Exception as e:
            session.rollback()
            logging.error("修改任务状态失败", e)
            raise False
        finally:
            session.close()

    def update_job_status_failed(self, job_id):
        """
        desc：修改任务状态为失败
        param：job_id 任务id
        return: True or False
       """
        # 设置job 参数
        job = self.find_job(job_id)
        job.set_job_end_time()
        job.set_job_consume_time()
        job.set_job_status(JOB_STATUS_FAILED)
        return self.update_job_status(job)

    def update_job_status_start(self, job):
        """
       修改任务状态为开始
       return:
       """
        job.set_job_start_time()
        job.job_status = JOB_STATUS_START
        return self.update_job_status(job)

    def update_job_status_success(self, job):
        """
       修改任务状态为成功
       return:
       """
        # 设置job 参数
        job.set_job_end_time()
        job.set_job_consume_time()
        job.set_job_status(JOB_STATUS_END)
        return self.update_job_status(job)

    def update_job_complete_percent(self, job):
        session = Session()
        try:
            data = {"job_complete_percent": job.job_complete_percent}
            flag = session.query(CyberspaceJob).filter(
                and_(CyberspaceJob.job_id == job.job_id, CyberspaceJob.job_status != JOB_STATUS_PAUSE)).update(data)
            session.commit()
            return flag == 1
        except Exception as e:
            session.rollback()
            logging.error("修改任务百分比失败", e)
            raise False
        finally:
            session.close()

    def find_result(self, ip):
        """
        desc: 根据ip 查找最新结果
        ip : ip地址
        return: 结果Result
        """
        session = Session()
        try:
            result = session.query(CyberspaceAssetResult).filter(CyberspaceAssetResult.ip == ip).one_or_none()
            return result
        except Exception as e:
            logging.error("查找ip查找任务结果失败", e)
        finally:
            session.close()
        pass

    def save_or_update_result(self, result):
        """
        desc: 修改result的结果
        result : 结果
        return: 结果Result
        """
        session = Session()
        try:
            history_result = session.query(CyberspaceAssetResult).filter(
                CyberspaceAssetResult.ip == result.ip).one_or_none()
            if history_result:
                session.query(CyberspaceAssetResult).filter(CyberspaceAssetResult.ip == result.ip).delete()
            session.add(result)
            session.commit()
            return True
        except Exception as e:
            session.rollback()
            logging.error("修改任务百分比失败", e)
            raise False
        finally:
            session.close()

    def save_and_move_result_to_history(self, cur_result, his_result):
        """
        desc: 保存当前结果，并且将之前结果移动到历史库中。
        cur_result: 当前数据，需要保存到数据库中的数据
        his_result: 历史数据，需要移动到历史库的数据
        """
        session = Session()
        try:
            # his_result需要结果表中的数据对比，如果表中的ip的时间不等于his_result的时间，
            # 说明当前在多进程的环境中，已经被修改，那么这个方法就结束了
            if his_result:
                result = session.query(CyberspaceAssetResult).filter(CyberspaceAssetResult.ip == his_result.ip).one()
                if result.create_time != his_result.create_time:
                    return
                # 如果满足上述条件，继续下边的操作
                # 从结果库中删除旧的数据
                session.query(CyberspaceAssetResult).filter(CyberspaceAssetResult.ip == his_result.ip).delete()
                # 添加历史库
                history = CyberspaceHistoryResult(
                    ip=his_result.ip,
                    hostname=his_result.hostname,
                    mac=his_result.mac,
                    mac_vender=his_result.mac_vender,
                    os_version=his_result.os_version,
                    device_type=his_result.device_type,
                    port_nums=his_result.port_nums,
                    server_info=his_result.server_info,
                    job_id=his_result.job_id,
                    job_name=his_result.job_name,
                    create_time=his_result.create_time,
                    insert_time=datetime.now()
                )
                session.add(history)
            # 将当前结果保存
            session.add(cur_result)
            session.commit()
        except Exception as e:
            session.rollback()
            logging.error("查找ip查找任务结果失败", e)
        finally:
            session.close()


    def pause_job(self, job_id):
        """
        desc暂停某个任务
        """
        session = Session()
        try:
            data = {"job_status": JOB_STATUS_PAUSE}
            flag = session.query(CyberspaceJob).filter(CyberspaceJob.job_id == job_id)\
                .filter(CyberspaceJob.job_status == JOB_STATUS_START)\
                .filter(CyberspaceJob.job_complete_percent < 100 - ASSET_JOB_COMPLETE_WRITE_JOB_TO_TABLE_WEIGHT)\
                .update(data)
            session.commit()
            return flag == 1
        except Exception as e:
            session.rollback()
            logging.error("修改任务为暂停状态失败", e)
            raise False
        finally:
            session.close()

    def restart_job(self, job_id):
        """
        desc重启某个任务
        """
        session = Session()
        try:
            data = {"job_status": JOB_STATUS_START}
            flag = session.query(CyberspaceJob).filter(CyberspaceJob.job_id == job_id) \
                .filter(CyberspaceJob.job_status == JOB_STATUS_PAUSE) \
                .update(data)
            session.commit()
            return flag == 1
        except Exception as e:
            session.rollback()
            logging.error("修改任务为运行状态失败", e)
            raise False
        finally:
            session.close()


jobDao = JobDao()
